// 监听简单对象
// const data = {}
// const name = 'ycd'
// Object.defineProperty(data, "name", {
//     // 监听数据模型变化返回一个内容
//     get: function () {
//         console.log('get')
//         return name
//     },
//     // 赋值一个内容
//     set: function (newVal) {
//         console.log('set')
//         name = newVal
//     }
// });

// 监听数组，复杂对象=>复杂监听




//触发更新视图
function updateView() {
    console.log('视图更新')
}

// 重新定义数组原型：
const oldArrayProperty=Array.prototype;
// 创建新对象，原型指向oldArrayProperty,不会影响原型
const arrProto=Object.create(oldArrayProperty);
['push','pop','shift','unshift','slice'].forEach(methodName=>{
    arrProto[methodName]=function(){
        updateView() //触发视图更新
        oldArrayProperty[methodName].call(this,...arguments)
    }
})

//重新定义属性，监听起来
function defineReactive(target, key, value) {
    // 深度监听
    observer(value)
    // 核心api
    Object.defineProperty(target, key, {
        get() {
            return value
        },
        set(newValue) {
            if (newValue !== value) {
                observer(newValue)
                value = newValue
                updateView()
            }
        }
    })
}
// 监听对象属性:
function observer(target) {
    if (typeof target !== 'object' || target === null) {
        return target
    }

    if(Array.isArray(target)){
        target.__proto__=arrProto
    }

    for (let key in target) {
        defineReactive(target, key, target[key])
    }
}


//准备数据
const data2 = {
    name: 'zhangsan',
    age: 20,
    info:{
        address:'杭州' //复杂数据需要深度监听
    },
    nums:[10,20,30]
}

observer(data2)

//测试数据
data2.name = 'lisi';
data2.age = 21;
data2.info.address='西湖'

data2.x='100' //新增的属性并能监听到，所以有Vue.set
delete data2.name //删除属性，监听不到，所以有Vue.delete
data2.nums.push('4')   //不具备监听数组的能力,需要重新定义数组原型赋值后再重新监听


/*------------------------Object.defineProperty缺点-----------------------*/

// 1.深度监听，需要递归到底，一次性计算量大
// 2.无法监听新增属性/删除属性(Vue.set Vue.delete)





// 使用Proxy
const data3={
    name:'ycd',
    age:20
}
// 返回新data
const proxyData=new Proxy(data3,{
    get(target,key,receiver){
        const result=Reflect.get(target,key,receiver)
        console.log('get',key)
        return result //返回结果
    },
    set(target,key,val,receiver){
        const result=Reflect.set(target,key,val,receiver)
        console.log('set',key,val)
        return result //是否设置成功
    },   
    deleteProperty(target,key){
        const result=Reflect.deleteProperty(target,key)
        console.log('deleteProperty',key)
        return result //是否删除成功
    }        
})